package com.lanchetech.admin.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.admin.service.CourseService;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.ColumnCourseAuthTypeEnum;
import com.lanchetech.common.enums.DeletedEnum;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.DaoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CourseServiceImpl implements CourseService {

    @Autowired
    CourseMapper courseMapper;

    @Autowired
    ColumnsMapper columnsMapper;

    @Autowired
    SkuColumnCourseMapper skuColumnCourseMapper;

    @Autowired
    SkuMapper skuMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    ColumnCourseAuthMapper columnCourseAuthMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    HomeworkMapper homeworkMapper;

    @Autowired
    HonorMapper honorMapper;

    @Autowired
    ExpFlowMapper expFlowMapper;

    /**
     * 模糊删除redis，支持通配符
     *
     * @param key
     */
    private void deleteRedisByKey(String key) {
        Set<String> keys = redisTemplate.keys(key);
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    private void updateColumnCourseCount(Long columnId){
        Long count = courseMapper.countByColumnIdAndDeleted(columnId, DeletedEnum.DEFAULT.getStatus());
        columnsMapper.updateCourseCountById(count.intValue(), columnId);
    }

    @Override
    public BaseResp editColumns(Columns req) {
        if (req.getId() == null) {
            req.setDeleted(DeletedEnum.DEFAULT.getStatus());
            req.setStudyCount(0L);
            req.setCourseCount(0);
            req.setCreatedAt(new Date());
            req.setUpdatedAt(new Date());
            columnsMapper.insert(req);
        } else {
            req.setUpdatedAt(new Date());
            columnsMapper.updateByPrimaryKeySelective(req);
        }
        deleteRedisByKey("HomeInfoResp");
        return new BaseResp();
    }

    @Override
    public ResultData<Columns> getColumnsDetail(Long id) {
        return new ResultData<>(columnsMapper.selectByPrimaryKey(id));
    }

    @Override
    public BaseResp deleteColumns(Long id) {
        columnsMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);
        deleteRedisByKey("HomeInfoResp");
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<Columns>> getColumnsPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Columns> list = columnsMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<List<Columns>> getColumnsList() {
        return new ResultData<>(columnsMapper.findAllNotDeleted());
    }

    @Override
    public ResultData<List<Course>> getCourseListByColumnIds(List<Long> columnIds) {
        return new ResultData<>(courseMapper.findAllByColumnIds(columnIds));
    }

    @Override
    public BaseResp editCourse(Course req) {
        if (req.getId() == null) {
            // 每个专栏最多只能有1000个课程
            Long count = courseMapper.countByColumnIdAndDeleted(req.getColumnId(), DeletedEnum.DEFAULT.getStatus());
            if(count != null && count > 1000){
                return new BaseResp(ResultCode.ONE_COLUMN_MAX_COURSE_COUNT);
            }

            req.setDeleted(DeletedEnum.DEFAULT.getStatus());
            req.setGoods(0);
            req.setViews(0);
            req.setStudyCount(0L);
            req.setCreatedAt(new Date());
            req.setUpdatedAt(new Date());
            courseMapper.insert(req);

            updateColumnCourseCount(req.getColumnId());
        } else {
            Course old = courseMapper.selectByPrimaryKey(req.getId());
            req.setUpdatedAt(new Date());
            courseMapper.updateByPrimaryKeySelective(req);

            if(!old.getColumnId().equals(req.getColumnId())){
                // 两个专栏的数量都要更新
                updateColumnCourseCount(req.getColumnId());
                updateColumnCourseCount(old.getColumnId());
            }
        }


        deleteRedisByKey("HomeInfoResp");
        return new BaseResp();
    }

    @Override
    public ResultData<Course> getCourseDetail(Long id) {
        return new ResultData<>(courseMapper.selectByPrimaryKey(id));
    }

    @Override
    public BaseResp deleteCourse(Long id) {
        courseMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);

        updateColumnCourseCount(courseMapper.selectByPrimaryKey(id).getColumnId());
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<Course>> getCoursePage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Course> list = courseMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp editSkuColumnCourse(List<SkuColumnCourse> req) {
        // 1、先sku列表 关联专栏 | 关联课程 2、关联专栏可以是多个，关联课程可以是多个 3、关联课程时，必须先选择专栏，然后再勾选课程。 4、课程或专栏需要分开设置和保存

        // 先清空所有关联
        skuColumnCourseMapper.deleteBySkuIdAndType(req.get(0).getSkuId(), req.get(0).getType());

        // 再插入
        req.stream().forEach(item -> {
            item.setCreatedAt(new Date());
        });
        skuColumnCourseMapper.batchInsert(req);

        return new BaseResp();
    }

    @Override
    public BaseResp deleteSkuColumnCourse(Long skuId, Byte type) {
        skuColumnCourseMapper.deleteBySkuIdAndType(skuId, type);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<SkuCourseBindVO>> getSkuPageWithBindCount(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Sku> skuList = skuMapper.findAllPage(req);

        Spu spu = spuMapper.selectByPrimaryKey(req.getSpuId());

        List<SkuColumnCourse> skuColumnCourseList = skuColumnCourseMapper.findAllBySpuId(req.getSpuId());

        Map<Long, Integer> columnMap = new HashMap<>();
        Map<Long, Integer> courseMap = new HashMap<>();


        if (!CollectionUtils.isEmpty(skuColumnCourseList)) {
            skuColumnCourseList.stream().forEach(item -> {
                if (ColumnCourseAuthTypeEnum.COLUMN.getType().equals(item.getType())) {
                    if (columnMap.containsKey(item.getSkuId())) {
                        columnMap.put(item.getSkuId(), columnMap.get(item.getSkuId()) + 1);
                    } else {
                        columnMap.put(item.getSkuId(), 1);
                    }
                } else {
                    if (courseMap.containsKey(item.getSkuId())) {
                        courseMap.put(item.getSkuId(), courseMap.get(item.getSkuId()) + 1);
                    } else {
                        courseMap.put(item.getSkuId(), 1);
                    }
                }
            });
        }


        List<SkuCourseBindVO> result = new ArrayList<>();
        skuList.stream().forEach(item -> {
            SkuCourseBindVO vo = new SkuCourseBindVO();
            BeanUtils.copyProperties(item, vo);
            vo.setSpuName(spu.getName());
            vo.setColumnCount(columnMap.get(item.getId()));
            vo.setCourseCount(courseMap.get(item.getId()));
            result.add(vo);
        });
        return PageHelpUtil.buildPage(result, page);
    }

    @Override
    public ResultData<List<SkuColumnCourse>> getSkuColumnCourseDetail(Long skuId, Byte type) {
        return new ResultData<>(skuColumnCourseMapper.findAllBySkuIdAndType(skuId, type));
    }

    @Override
    public ResultData<BasePageResp<ColumnCourseAuthVO>> getColumnCourseAuthPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ColumnCourseAuthVO> list = columnCourseAuthMapper.findAllPage(req);


        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ColumnCourseAuthVO::getUserId).collect(Collectors.toList()));

            List<Long> columnList = new ArrayList<>();
            List<Long> courseList = new ArrayList<>();
            list.stream().forEach(item -> {
                columnList.add(item.getColumnId());
                if (ColumnCourseAuthTypeEnum.COURSE.getType().equals(item.getType())) {
                    courseList.add(item.getCourseId());
                }
            });
            Map<Long, Columns> columnMap = daoService.getColumnMap(columnList);
            Map<Long, Course> courseMap = courseList.size() > 0 ? daoService.getCourseMap(courseList) : new HashMap<>();

            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
                item.setColumnTitle(columnMap.get(item.getColumnId()).getTitle());
                item.setColumnImage(columnMap.get(item.getColumnId()).getImage());
                if (ColumnCourseAuthTypeEnum.COURSE.getType().equals(item.getType())) {
                    item.setCourseTitle(courseMap.get(item.getCourseId()).getTitle());
                }
            });
        }

        return PageHelpUtil.buildPage(list, page);
    }


    @Override
    public ResultData<BasePageResp<HomeworkVO>> getHomeworkPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<HomeworkVO> list = homeworkMapper.findAllPage(req);

        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(HomeworkVO::getUserId).collect(Collectors.toList()));
            Map<Long, Course> courseMap = daoService.getCourseMap(list.stream().map(Homework::getCourseId).collect(Collectors.toList()));

            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
                item.setCourseImage(courseMap.get(item.getCourseId()).getMainImage());
                item.setCourseTitle(courseMap.get(item.getCourseId()).getTitle());
            });
        }

        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<ExpFlowVO>> getExpFlowPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ExpFlow> list = expFlowMapper.findAllPage(req);

        List<ExpFlowVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ExpFlow::getUserId).collect(Collectors.toList()));

            list.stream().forEach(item -> {
                ExpFlowVO vo = new ExpFlowVO();
                BeanUtils.copyProperties(item, vo);
                vo.setAvatar(userMap.get(item.getUserId()).getAvatar());
                vo.setNickname(userMap.get(item.getUserId()).getNickname());
                result.add(vo);
            });
        }

        return PageHelpUtil.buildPage(result, page);
    }

    @Override
    public BaseResp editHomeworkReply(Homework req) {
        req.setUpdatedAt(new Date());
        homeworkMapper.updateByPrimaryKeySelective(req);
        return new BaseResp();
    }

}